#include "AnimationManager.h"
#include <string>
#include <string.h>
#include "../tinyxml/tinyxml.h"



#include <cassert>

CAnimationManager * CAnimationManager::s_Instance = nullptr;

//CAnimationManager::CAnimationManager()
//{
//}


//CAnimationManager::~CAnimationManager()
//{
//}

bool CAnimationManager::Initialize() // Contains a lot of test stuff
{
	LoadXmlFile("Resources/Sprites/BossAnim.xml");
	LoadXmlFile("Resources/Sprites/blueRunnerAnim.xml");
	LoadXmlFile("Resources/Sprites/redRunnerAnim.xml");
	LoadXmlFile("Resources/Sprites/blueStrikerAnim.xml");
	LoadXmlFile("Resources/Sprites/redStrikerAnim.xml");
	LoadXmlFile("Resources/Sprites/blueBomberAnim.xml");
	LoadXmlFile("Resources/Sprites/redBomberAnim.xml");
	LoadXmlFile("Resources/Sprites/blueTankAnim.xml");
	LoadXmlFile("Resources/Sprites/redTankAnim.xml");
	LoadXmlFile("Resources/Sprites/orbAnim.xml");
	// add more calls as need be

	return true;
}

void CAnimationManager::LoadXmlFile(const char * fileName)
{
	// Test XML
	TiXmlDocument testSetup(fileName);

	if (testSetup.LoadFile() == true)
	{
		double info;

		double numAnim;

		double infoL;
		double infoT;
		double infoR;
		double infoB;

		double loadNum;

		const char * text;
		const char * text2;
		const char * trigg;

		bool load = true;

		TiXmlElement* tRoot = testSetup.RootElement();

		tRoot->Attribute("num", &numAnim);

		TiXmlElement* tnode = tRoot->FirstChildElement("anim");

		for (int x = 0; x < (int)numAnim; x++)
		{
			if (x > 0)
				tnode = tnode->NextSiblingElement("anim");

			CAnimation * animAdd = new CAnimation();

			TiXmlElement* frame = tnode->FirstChildElement("animName");

			text = frame->GetText();

			std::string s = text;
			
			animAdd->SetName(s);
			frame = frame->NextSiblingElement("animImage");

			
			
			text2 = frame->GetText();
			std::string temp = text2;
			std::string temp2 = "Resources/Images/";
			std::string fin = temp2 + temp;

			frame = frame->NextSiblingElement("testInfo");
			frame->Attribute("numFrames", &loadNum);
			frame->Attribute("backColorR", &infoR);
			frame->Attribute("backColorG", &infoT);
			frame->Attribute("backColorB", &infoB);
			
			
			SGD::Color color = SGD::Color((int)infoR, (int)infoT, (int)infoB);
			
			frame->Attribute("playing", &info);
			if ((int)info == 1)
				animAdd->m_bPlaying = true;
			else
				animAdd->m_bPlaying = false;

			frame->Attribute("looping", &info);
			if ((int)info == 1)
				animAdd->m_bLooping = true;
			else
				animAdd->m_bLooping = false;

			animAdd->m_hImage = SGD::GraphicsManager::GetInstance()->LoadTexture(fin.c_str(), color);


			for (int i = 0; i < loadNum; i++)
			{
				CFrame frameAdd;

				frame = frame->NextSiblingElement("frame");

				frame->Attribute("duration", &info);
				frameAdd.SetDuration(float(info));

				frame->Attribute("sourceRectL", &infoL);
				frame->Attribute("sourceRectT", &infoT);
				frame->Attribute("sourceRectR", &infoR);
				frame->Attribute("sourceRectB", &infoB);

				SGD::Rectangle rect{ (float)infoL, (float)infoT, (float)infoR, (float)infoB };
				frameAdd.SetFrame(rect);

				frame->Attribute("anchorX", &info);
				frame->Attribute("anchorY", &infoL);
				SGD::Point point{ (float)info, (float)infoL };
				frameAdd.SetAnchor(point);

				trigg = frame->Attribute("trigger");
				frameAdd.cTrigger = trigg;

				frame->Attribute("numAR", &info);

				if (info > 0)
				{
					for (int f = 0; f < info; f++)
					{
						frame = frame->NextSiblingElement("active");

						frame->Attribute("activeL", &infoL);
						frame->Attribute("activeT", &infoT);
						frame->Attribute("actvieR", &infoR);
						frame->Attribute("activeB", &infoB);

						SGD::Rectangle rect{ (float)infoL, (float)infoT, (float)infoR, (float)infoB };
						frameAdd.AddActiveHit(rect);
					}
				}

				frame = frame->NextSiblingElement("passive");
				frame->Attribute("passiveL", &infoL);
				frame->Attribute("passiveT", &infoT);
				frame->Attribute("passiveR", &infoR);
				frame->Attribute("passiveB", &infoB);

				SGD::Rectangle rekt{ (float)infoL, (float)infoT, (float)infoR, (float)infoB };
				frameAdd.AddPassHit(rekt);
				/*********************************************************************/
				// Need to start adding stuff for collision rect vectors within frame

				animAdd->vFrames.push_back(frameAdd);
			}

			this->AddAnimation(animAdd, text);
			
		}
	}
	
}

void CAnimationManager::SetOwner(Entity * owner, std::string key)
{
	CAnimation anim;
	anim = *AnimationMap.at(key);
	owner->currAnimation = anim;
	owner->currAnimation.SetOwner(owner);
}

void CAnimationManager::AddAnimation(CAnimation* pAnimation, std::string key)
{
	// Check the parameter
	assert(pAnimation != nullptr && "AnimationManager::AddAnimation - parameter cannot be null");

	// Add to the map
	AnimationMap.insert(std::pair<std::string, CAnimation*>(key, pAnimation));

}

void CAnimationManager::RemoveAll(void)
{
	for (auto it = AnimationMap.begin(); it != AnimationMap.end(); ++it)
	{
		SGD::GraphicsManager::GetInstance()->UnloadTexture(it->second->m_hImage);
		
		delete it->second;
	}
	AnimationMap.clear();
	this->currAnim.clear();
}

void CAnimationManager::AddAnim(CAnimation * anim2Play)
{
	this->currAnim.push_back(anim2Play);
}

void CAnimationManager::UpdateAll(float elapsedTime)
{
	for (std::vector<CAnimation*>::size_type i = 0; i != currAnim.size(); i++)
	{
		currAnim[i]->Update(elapsedTime);
		if (currAnim[i]->IsFinished() == true)
		{
			currAnim.erase(currAnim.begin() + i);
			currAnim.shrink_to_fit();
			i--;
		}
	}
}

void CAnimationManager::RenderAll(void) 
{
	for (std::vector<CAnimation*>::size_type i = 0; i != currAnim.size(); i++)
	{
		if (currAnim[i]->GetOwner()->CheckActive() == true)
		{
			SGD::Color color{ 255, 255, 255 };
			currAnim[i]->Render(currAnim[i]->GetOwner()->GetPosition(), false, 1.0f, color);
		}
	}
}

CAnimationManager * CAnimationManager::GetInstance(void)
{
	static CAnimationManager s_Instance;

	return &s_Instance;
}

void CAnimationManager::DeleteInstance()
{
	delete s_Instance;
	s_Instance = nullptr;
}
